home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / gtk-2.0 / dsextras.py
Text File  |  2009-10-09  |  15KB  |  434 lines

  1. #
  2. # dsextras.py - Extra classes and utilities for distutils, adding
  3. #               pkg-config support
  4.  
  5.  
  6. from distutils.command.build_ext import build_ext
  7. from distutils.command.install_lib import install_lib
  8. from distutils.command.install_data import install_data
  9. from distutils.extension import Extension
  10. import distutils.dep_util
  11. import fnmatch
  12. import os
  13. import re
  14. import string
  15. import sys
  16.  
  17. GLOBAL_INC = []
  18. GLOBAL_MACROS = []
  19.  
  20. def get_m4_define(varname):
  21.     """Return the value of a m4_define variable as set in configure.in."""
  22.     pattern = re.compile("m4_define\(" + varname + "\,\s*(.+)\)")
  23.     if os.path.exists('configure.ac'):
  24.         fname = 'configure.ac'
  25.     elif os.path.exists('configure.in'):
  26.         fname = 'configure.in'
  27.     else:
  28.         raise SystemExit('could not find configure file')
  29.  
  30.     for line in open(fname).readlines():
  31.         match_obj = pattern.match(line)
  32.         if match_obj:
  33.             return match_obj.group(1)
  34.  
  35.     return None
  36.  
  37. def getoutput(cmd):
  38.     """Return output (stdout or stderr) of executing cmd in a shell."""
  39.     return getstatusoutput(cmd)[1]
  40.  
  41. def getstatusoutput(cmd):
  42.     """Return (status, output) of executing cmd in a shell."""
  43.     if sys.platform == 'win32':
  44.         pipe = os.popen(cmd, 'r')
  45.         text = pipe.read()
  46.         sts = pipe.close() or 0
  47.         if text[-1:] == '\n':
  48.             text = text[:-1]
  49.         return sts, text
  50.     else:
  51.         from commands import getstatusoutput
  52.         return getstatusoutput(cmd)
  53.  
  54. def have_pkgconfig():
  55.     """Checks for the existence of pkg-config"""
  56.     if (sys.platform == 'win32' and
  57.         os.system('pkg-config --version > NUL') == 0):
  58.         return 1
  59.     else:
  60.         if getstatusoutput('pkg-config')[0] == 256:
  61.             return 1
  62.  
  63. def list_files(dir):
  64.     """List all files in a dir, with filename match support:
  65.     for example: glade/*.glade will return all files in the glade directory
  66.     that matches *.glade. It also looks up the full path"""
  67.     if dir.find(os.sep) != -1:
  68.         parts = dir.split(os.sep)
  69.         dir = string.join(parts[:-1], os.sep)
  70.         pattern = parts[-1]
  71.     else:
  72.         pattern = dir
  73.         dir = '.'
  74.  
  75.     dir = os.path.abspath(dir)
  76.     retval = []
  77.     for file in os.listdir(dir):
  78.         if fnmatch.fnmatch(file, pattern):
  79.             retval.append(os.path.join(dir, file))
  80.     return retval
  81.  
  82. def pkgc_version_check(name, req_version):
  83.     """Check the existence and version number of a package:
  84.     returns 0 if not installed or too old, 1 otherwise."""
  85.     is_installed = not os.system('pkg-config --exists %s' % name)
  86.     if not is_installed:
  87.         return 0
  88.  
  89.     orig_version = getoutput('pkg-config --modversion %s' % name)
  90.     version = map(int, orig_version.split('.'))
  91.     pkc_version = map(int, req_version.split('.'))
  92.  
  93.     if version >= pkc_version:
  94.         return 1
  95.         
  96.     return 0
  97.  
  98. class BuildExt(build_ext):
  99.     def init_extra_compile_args(self):
  100.         self.extra_compile_args = []
  101.         if sys.platform == 'win32' and \
  102.            self.compiler.compiler_type == 'mingw32':
  103.             # MSVC compatible struct packing is required.
  104.             # Note gcc2 uses -fnative-struct while gcc3
  105.             # uses -mms-bitfields. Based on the version
  106.             # the proper flag is used below.
  107.             msnative_struct = { '2' : '-fnative-struct',
  108.                                 '3' : '-mms-bitfields' }
  109.             gcc_version = getoutput('gcc -dumpversion')
  110.             print 'using MinGW GCC version %s with %s option' % \
  111.                   (gcc_version, msnative_struct[gcc_version[0]])
  112.             self.extra_compile_args.append(msnative_struct[gcc_version[0]])
  113.  
  114.     def modify_compiler(self):
  115.         if sys.platform == 'win32' and \
  116.            self.compiler.compiler_type == 'mingw32':
  117.             # Remove '-static' linker option to prevent MinGW ld
  118.             # from trying to link with MSVC import libraries.
  119.             if self.compiler.linker_so.count('-static'):
  120.                 self.compiler.linker_so.remove('-static')
  121.  
  122.     def build_extensions(self):
  123.         # Init self.extra_compile_args
  124.         self.init_extra_compile_args()
  125.         # Modify default compiler settings
  126.         self.modify_compiler()
  127.         # Invoke base build_extensions()
  128.         build_ext.build_extensions(self)
  129.  
  130.     def build_extension(self, ext):
  131.         # Add self.extra_compile_args to ext.extra_compile_args
  132.         ext.extra_compile_args += self.extra_compile_args
  133.         # Generate eventual templates before building
  134.         if hasattr(ext, 'generate'):
  135.             ext.generate()
  136.         # Filter out 'c' and 'm' libs when compilic w/ msvc
  137.         if sys.platform == 'win32' and self.compiler.compiler_type == 'msvc':
  138.             save_libs = ext.libraries
  139.             ext.libraries = [lib for lib in ext.libraries 
  140.                              if lib not in ['c', 'm']]
  141.         else:
  142.             save_libs = ext.libraries
  143.         # Invoke base build_extension()
  144.         build_ext.build_extension(self, ext)
  145.         if save_libs != None and save_libs != ext.libraries:
  146.             ext.libraries = save_libs
  147.  
  148. class InstallLib(install_lib):
  149.  
  150.     local_outputs = []
  151.     local_inputs = []
  152.  
  153.     def set_install_dir(self, install_dir):
  154.         self.install_dir = install_dir
  155.  
  156.     def get_outputs(self):
  157.         return install_lib.get_outputs(self) + self.local_outputs
  158.  
  159.     def get_inputs(self):
  160.         return install_lib.get_inputs(self) + self.local_inputs
  161.  
  162. class InstallData(install_data):
  163.  
  164.     local_outputs = []
  165.     local_inputs = []
  166.     template_options = {}
  167.  
  168.     def prepare(self):
  169.         if os.name == "nt":
  170.             self.prefix = os.sep.join(self.install_dir.split(os.sep)[:-3])
  171.         else:
  172.             # default: os.name == "posix"
  173.             self.prefix = os.sep.join(self.install_dir.split(os.sep)[:-4])
  174.  
  175.         self.exec_prefix = '${prefix}/bin'
  176.         self.includedir = '${prefix}/include'
  177.         self.libdir = '${prefix}/lib'
  178.         self.datarootdir = '${prefix}/share'
  179.         self.datadir = '${prefix}/share'
  180.  
  181.         self.add_template_option('prefix', self.prefix)
  182.         self.add_template_option('exec_prefix', self.exec_prefix)
  183.         self.add_template_option('includedir', self.includedir)
  184.         self.add_template_option('libdir', self.libdir)
  185.         self.add_template_option('datarootdir', self.datarootdir)
  186.         self.add_template_option('datadir', self.datadir)
  187.         self.add_template_option('PYTHON', sys.executable)
  188.         self.add_template_option('THREADING_CFLAGS', '')
  189.  
  190.     def set_install_dir(self, install_dir):
  191.         self.install_dir = install_dir
  192.  
  193.     def add_template_option(self, name, value):
  194.         self.template_options['@%s@' % name] = value
  195.  
  196.     def install_template(self, filename, install_dir):
  197.         """Install template filename into target directory install_dir."""
  198.         output_file = os.path.split(filename)[-1][:-3]
  199.  
  200.         template = open(filename).read()
  201.         for key, value in self.template_options.items():
  202.             template = template.replace(key, value)
  203.  
  204.         output = os.path.join(install_dir, output_file)
  205.         self.mkpath(install_dir)
  206.         open(output, 'w').write(template)
  207.         self.local_inputs.append(filename)
  208.         self.local_outputs.append(output)
  209.         return output
  210.  
  211.     def get_outputs(self):
  212.         return install_data.get_outputs(self) + self.local_outputs
  213.  
  214.     def get_inputs(self):
  215.         return install_data.get_inputs(self) + self.local_inputs
  216.  
  217. class PkgConfigExtension(Extension):
  218.     # Name of pygobject package extension depends on, can be None
  219.     pygobject_pkc = 'pygobject-2.0'
  220.     can_build_ok = None
  221.     def __init__(self, **kwargs):
  222.         name = kwargs['pkc_name']
  223.         kwargs['include_dirs'] = self.get_include_dirs(name) + GLOBAL_INC
  224.         kwargs['define_macros'] = GLOBAL_MACROS
  225.         kwargs['libraries'] = self.get_libraries(name)
  226.         kwargs['library_dirs'] = self.get_library_dirs(name)
  227.         if 'pygobject_pkc' in kwargs:
  228.             self.pygobject_pkc = kwargs.pop('pygobject_pkc')
  229.         if self.pygobject_pkc:
  230.             kwargs['include_dirs'] += self.get_include_dirs(self.pygobject_pkc)
  231.             kwargs['libraries'] += self.get_libraries(self.pygobject_pkc)
  232.             kwargs['library_dirs'] += self.get_library_dirs(self.pygobject_pkc)
  233.         self.name = kwargs['name']
  234.         self.pkc_name = kwargs['pkc_name']
  235.         self.pkc_version = kwargs['pkc_version']
  236.         del kwargs['pkc_name'], kwargs['pkc_version']
  237.         Extension.__init__(self, **kwargs)
  238.  
  239.     def get_include_dirs(self, names):
  240.         if type(names) != tuple:
  241.             names = (names,)
  242.         retval = []
  243.         for name in names:
  244.             output = getoutput('pkg-config --cflags-only-I %s' % name)
  245.             retval.extend(output.replace('-I', '').split())
  246.         return retval
  247.  
  248.     def get_libraries(self, names):
  249.         if type(names) != tuple:
  250.             names = (names,)
  251.         retval = []
  252.         for name in names:
  253.             output = getoutput('pkg-config --libs-only-l %s' % name)
  254.             retval.extend(output.replace('-l', '').split())
  255.         return retval
  256.  
  257.     def get_library_dirs(self, names):
  258.         if type(names) != tuple:
  259.             names = (names,)
  260.         retval = []
  261.         for name in names:
  262.             output = getoutput('pkg-config --libs-only-L %s' % name)
  263.             retval.extend(output.replace('-L', '').split())
  264.         return retval
  265.  
  266.     def can_build(self):
  267.         """If the pkg-config version found is good enough"""
  268.         if self.can_build_ok != None:
  269.             return self.can_build_ok
  270.  
  271.         if type(self.pkc_name) != tuple:
  272.             reqs = [(self.pkc_name, self.pkc_version)]
  273.         else:
  274.             reqs = zip(self.pkc_name, self.pkc_version)
  275.  
  276.         for package, version in reqs:
  277.             retval = os.system('pkg-config --exists %s' % package)
  278.             if retval:
  279.                 print ("* %s.pc could not be found, bindings for %s"
  280.                        " will not be built." % (package, self.name))
  281.                 self.can_build_ok = 0
  282.                 return 0
  283.  
  284.             orig_version = getoutput('pkg-config --modversion %s' %
  285.                                      package)
  286.             if (map(int, orig_version.split('.')) >=
  287.                 map(int, version.split('.'))):
  288.                 self.can_build_ok = 1
  289.                 return 1
  290.             else:
  291.                 print "Warning: Too old version of %s" % self.pkc_name
  292.                 print "         Need %s, but %s is installed" % \
  293.                       (package, orig_version)
  294.                 self.can_build_ok = 0
  295.                 return 0
  296.  
  297.     def generate(self):
  298.         pass
  299.  
  300. # The Template and TemplateExtension classes require codegen which is
  301. # currently part of the pygtk distribution. While codegen might ultimately
  302. # be moved to pygobject, it was decided (bug #353849) to keep the Template
  303. # and TemplateExtension code in dsextras. In the meantime, we check for the
  304. # availability of codegen and redirect the user to the pygtk installer if
  305. # he/she wants to get access to Template and TemplateExtension.
  306.  
  307. template_classes_enabled=True
  308. codegen_error_message="""
  309. ***************************************************************************
  310. Codegen could not be found on your system and is required by the
  311. dsextras.Template and dsextras.TemplateExtension classes. codegen is part
  312. of PyGTK. To use either Template or TemplateExtension, you should also
  313. install PyGTK.
  314. ***************************************************************************
  315. """
  316. try:
  317.     from codegen.override import Overrides
  318.     from codegen.defsparser import DefsParser
  319.     from codegen.codegen import register_types, SourceWriter, \
  320.          FileOutput
  321.     import codegen.createdefs
  322. except ImportError, e:
  323.     template_classes_enabled=False
  324.  
  325. class Template(object):
  326.     def __new__(cls,*args, **kwds):
  327.         if not template_classes_enabled:
  328.             raise NameError("'%s' is not defined\n" % cls.__name__
  329.                             + codegen_error_message)    
  330.         return object.__new__(cls,*args, **kwds)
  331.  
  332.     def __init__(self, override, output, defs, prefix,
  333.                  register=[], load_types=None, py_ssize_t_clean=False):
  334.         
  335.         self.override = override
  336.         self.output = output
  337.         self.prefix = prefix
  338.         self.load_types = load_types
  339.         self.py_ssize_t_clean = py_ssize_t_clean
  340.  
  341.         self.built_defs=[]
  342.         if isinstance(defs,tuple):
  343.             self.defs=defs[0]
  344.             self.built_defs.append(defs)
  345.         else:
  346.             self.defs=defs
  347.  
  348.         self.register=[]
  349.         for r in register:
  350.             if isinstance(r,tuple):
  351.                 self.register.append(r[0])
  352.                 self.built_defs.append(r)
  353.             else:
  354.                 self.register.append(r)
  355.  
  356.     def check_dates(self):
  357.         # Return True if files are up-to-date
  358.         files=self.register[:]
  359.         files.append(self.override)
  360.         files.append(self.defs)
  361.  
  362.         return not distutils.dep_util.newer_group(files,self.output)
  363.  
  364.     def generate_defs(self):
  365.         for (target,sources) in self.built_defs:
  366.             if distutils.dep_util.newer_group(sources,target):
  367.                 # createdefs is mostly called from the CLI !
  368.                 args=['dummy',target]+sources
  369.                 codegen.createdefs.main(args)
  370.  
  371.  
  372.     def generate(self):
  373.         # Generate defs files if necessary
  374.         self.generate_defs()
  375.         # ... then check the file timestamps
  376.         if self.check_dates():
  377.             return
  378.  
  379.         for item in self.register:
  380.             dp = DefsParser(item,dict(GLOBAL_MACROS))
  381.             dp.startParsing()
  382.             register_types(dp)
  383.  
  384.         if self.load_types:
  385.             globals = {}
  386.             execfile(self.load_types, globals)
  387.  
  388.         dp = DefsParser(self.defs,dict(GLOBAL_MACROS))
  389.         dp.startParsing()
  390.         register_types(dp)
  391.  
  392.         fd = open(self.output, 'w')
  393.         sw = SourceWriter(dp,Overrides(self.override),
  394.                           self.prefix,FileOutput(fd,self.output))
  395.         sw.write(self.py_ssize_t_clean)
  396.         fd.close()
  397.  
  398. class TemplateExtension(PkgConfigExtension):
  399.     def __new__(cls,*args, **kwds):
  400.         if not template_classes_enabled:
  401.             raise NameError("'%s' is not defined\n" % cls.__name__
  402.                             + codegen_error_message)    
  403.         return PkgConfigExtension.__new__(cls,*args, **kwds)
  404.     
  405.     def __init__(self, **kwargs):
  406.         name = kwargs['name']
  407.         defs = kwargs['defs']
  408.         if isinstance(defs,tuple):
  409.             output = defs[0][:-5] + '.c'
  410.         else:
  411.             output = defs[:-5] + '.c'
  412.         override = kwargs['override']
  413.         load_types = kwargs.get('load_types')
  414.         py_ssize_t_clean = kwargs.pop('py_ssize_t_clean',False)
  415.         self.templates = []
  416.         self.templates.append(Template(override, output, defs, 'py' + name,
  417.                                        kwargs['register'], load_types,
  418.                                        py_ssize_t_clean))
  419.  
  420.         del kwargs['register'], kwargs['override'], kwargs['defs']
  421.         if load_types:
  422.             del kwargs['load_types']
  423.  
  424.         if kwargs.has_key('output'):
  425.             kwargs['name'] = kwargs['output']
  426.             del kwargs['output']
  427.  
  428.         PkgConfigExtension.__init__(self, **kwargs)
  429.  
  430.     def generate(self):
  431.         map(lambda x: x.generate(), self.templates)
  432.  
  433.  
  434.